/*
 * max7221.h
 *
 *  Created on: Apr 23, 2012
 *      Author: Robert Elliott
 */
#ifndef max7221_H_
#define max7221_H_

#include "msp430f5172.h"

// Function definitions
inline void spiOut(unsigned char data);
inline void maxInit(void);
inline void maxReg(unsigned char reg, unsigned char data);
inline void brightness(unsigned char light);
inline void clear_led(void);
inline void startup(void);
inline void healing(void);
inline void damaging(void);

// PINS on MSP 430f5172 
#define CS BIT5
#define MOSI BIT4
#define CLK BIT3
#define LOW 0
#define HIGH 1
#define NOOP   0x00

// LED addressing
#define DIGIT0 0x01
#define LEDBANK 0x01
#define LED1 0x4  << 0
#define LED2 LED1 << 1
#define LED3 LED1 << 2
#define LED4 LED1 << 3
#define LED5 LED1 << 4
#define LED6 LED1 << 5
#define ALL_LEDS LED1|LED2|LED3|LED4|LED5|LED6
#define DIGIT1 0x02
#define DIGIT2 0x03
#define DIGIT3 0x04
#define DIGIT4 0x05
#define DIGIT5 0x06
#define DIGIT6 0x07
#define DIGIT7 0x08

// LED Driver modes 
#define DECODEMODE  0x09
#define INTENSITY   0x0A
#define SCANLIMIT   0x0B
#define SHUTDOWN    0x0C
#define DISPLAYTEST 0x0F


// send byte over software SPI
// takes a character and parses it into it's bits
// sends data out MSB first
inline void spiOut(unsigned char data)
{
	unsigned int i;
	unsigned char mask = 0x80;			// 1000_0000 in binary
	for(i = 0; i < 8; i++)
	{
		P1OUT &= ~CLK;						// set clock initially low
		__delay_cycles(100);				// delay, might not need
		if((data & mask))					// if the data matches the mask send high
			P1OUT |= MOSI;					// pin goes high
		else
			P1OUT &= ~MOSI;				// else set low
		P1OUT |= CLK;						// set clk high at end of each bit
		__delay_cycles(100);
		mask = mask >> 0x01;				// shift the bit to the right by 1
	}
}

// send single character for brightness
// Note, goes for all LEDs
inline void brightness(unsigned char light)
{
	maxReg(INTENSITY, light);
}

// Cycles through LEDs and sets to low
inline void clear_led()
{
	unsigned char reg;
	for(reg = DIGIT0; reg <= DIGIT7; reg++)
	{
		maxReg(reg, 0x00);
		__delay_cycles(100000);
	}
}


inline void maxInit()
{
	P1DIR |= BIT3 + BIT4 + BIT5; // sets P1.3-1.4 as outputs
	__delay_cycles(1000);
	P1OUT &= ~CLK;
	P1OUT |= CS;
	__delay_cycles(10000);
	maxReg(SCANLIMIT, 0x00);	// use all rows/digits
	maxReg(INTENSITY, 0x0F);	// Brightness > 9000
	maxReg(DECODEMODE, 0x00);	// pixels, not integers
	maxReg(DISPLAYTEST, 0x00);	// not in test mode
	__delay_cycles(100);
	maxReg(SHUTDOWN, 0x01);		// Normal operation
	__delay_cycles(100);
}

inline void maxReg(unsigned char reg, unsigned char data)
{
	P1OUT &= ~CS;
	__delay_cycles(100);
	spiOut(reg);				// set the register
	spiOut(data);				// send the data
	P1OUT |= CS;				// set the chip select high
	P1OUT &= ~CLK;
	__delay_cycles(100);
}

// visual function for when the MCU starts up
inline void startup(void)
{
	unsigned char red  = LED1 | LED3 | LED5;
	unsigned char blue = LED2 | LED4 | LED6;
	unsigned char bright = 0x00;
	unsigned char reg;

	// Turn on all the red LEDs
	for(reg = DIGIT0; reg <= DIGIT7; reg++)
	{
		maxReg(reg, red);
		__delay_cycles(1000000);
	}
	// gradually bring the brightness up
	while(bright < 0x0F)
	{
		brightness(bright++);
		__delay_cycles(1000000);
		__delay_cycles(1000000);
	}
	// then turn them off
	clear_led();

	// enable all of the blue LEDs
	for(reg = DIGIT0; reg <= DIGIT7; reg++)
	{
		maxReg(reg, blue);
		__delay_cycles(1000000);
	}

	// fade in the brightness
	while(bright < 0x0F)
	{
		brightness(bright++);
		__delay_cycles(1000000);
		__delay_cycles(1000000);
	}
	// then turn them off
	clear_led();
	__delay_cycles(1000000);
	__delay_cycles(1000000);
	// bring up all leds
	for(reg = DIGIT0; reg <= DIGIT7; reg++)
	{
		maxReg(reg, ALL_LEDS);
		__delay_cycles(10000);
	}
	brightness(0x0A);
	__delay_cycles(100000);
	__delay_cycles(100000);

	// then turn them off
	brightness(0x00);
	clear_led();
		
}

inline void damaging(void)
{
	unsigned char red  = LED1 | LED3 | LED5;
	unsigned char bright = 0x00;
	unsigned char reg;
	
	for(reg = DIGIT0; reg <= DIGIT7; reg++)
	{
		maxReg(reg, red);
		__delay_cycles(10000);
	}
	while(count <= 4)
	{
		for(bright = 0x00; bright <= 0x0F; bright ++)
		{
			brightness(bright);
			__delay_cycles(1000000);
			__delay_cycles(1000000);
		}
		__delay_cycles(100000);
		__delay_cycles(100000);
		for(bright = 0x0F; bright >= 0x00; bright--)
		{
			brightness(bright);
			__delay_cycles(1000000);
			__delay_cycles(1000000);
		}
		__delay_cycles(100000);
		__delay_cycles(100000);
		__delay_cycles(100000);
	}

}

inline void healing(void)
{
	unsigned char blue  = LED2 | LED4 | LED6;
	unsigned char bright = 0x00;
	unsigned char reg;
	
	for(reg = DIGIT0; reg <= DIGIT7; reg++)
	{
		maxReg(reg, blue);
		__delay_cycles(10000);
	}
	while(count <= 4)
	{
		for(bright = 0x00; bright <= 0x0F; bright ++)
		{
			brightness(bright);
			__delay_cycles(1000000);
			__delay_cycles(1000000);
		}
		__delay_cycles(100000);
		__delay_cycles(100000);
		for(bright = 0x0F; bright >= 0x00; bright--)
		{
			brightness(bright);
			__delay_cycles(1000000);
			__delay_cycles(1000000);
		}
		__delay_cycles(100000);
		__delay_cycles(100000);
		__delay_cycles(100000);
	}
}

#endif
